[https://nvbugs/6480621][test] Revert to 60-second KV transfer timeout for GB300 DeepSeek V4 Pro disaggregated perf-sanity - #17137
Conversation
|
/bot run --disable-fail-fast --stage-list "GB300-44_GPUs-11_Nodes-PyTorch-Disagg-PerfSanity-CTX3-NODE1-GPU4-GEN1-NODE8-GPU32-Post-Merge-2" |
|
/bot run --disable-fail-fast --disable-reuse-test --stage-list "GB300-44_GPUs-11_Nodes-PyTorch-Disagg-PerfSanity-CTX3-NODE1-GPU4-GEN1-NODE8-GPU32-Post-Merge-2" |
|
PR_Github #63105 [ run ] triggered by Bot. Commit: |
|
PR_Github #63106 [ run ] triggered by Bot. Commit: |
|
PR_Github #63105 [ run ] completed with state |
|
PR_Github #63106 [ run ] completed with state |
|
/bot run --disable-fail-fast --disable-reuse-test --stage-list "GB300-44_GPUs-11_Nodes-PyTorch-Disagg-PerfSanity-CTX3-NODE1-GPU4-GEN1-NODE8-GPU32-Post-Merge-1" |
|
PR_Github #63144 [ run ] triggered by Bot. Commit: |
|
PR_Github #63144 [ run ] completed with state
|
|
/bot run --disable-fail-fast --disable-reuse-test --stage-list "GB300-44_GPUs-11_Nodes-PyTorch-Disagg-PerfSanity-CTX3-NODE1-GPU4-GEN1-NODE8-GPU32-Post-Merge-1" |
|
PR_Github #63150 [ run ] triggered by Bot. Commit: |
|
PR_Github #63150 [ run ] completed with state
|
|
/bot run --disable-fail-fast --disable-reuse-test --stage-list "GB300-44_GPUs-11_Nodes-PyTorch-Disagg-PerfSanity-CTX3-NODE1-GPU4-GEN1-NODE8-GPU32-Post-Merge-1" |
|
PR_Github #63165 [ run ] triggered by Bot. Commit: |
|
PR_Github #63165 [ run ] completed with state
|
38ca970 to
3e6c120
Compare
|
/bot run --disable-fail-fast --disable-reuse-test --stage-list "GB300-44_GPUs-11_Nodes-PyTorch-Disagg-PerfSanity-CTX3-NODE1-GPU4-GEN1-NODE8-GPU32-Post-Merge-1" |
|
PR_Github #63555 [ run ] triggered by Bot. Commit: |
|
PR_Github #63555 [ run ] completed with state
|
3e6c120 to
b7bd98a
Compare
|
/bot run --disable-fail-fast --disable-reuse-test --stage-list "GB300-44_GPUs-11_Nodes-PyTorch-Disagg-PerfSanity-CTX3-NODE1-GPU4-GEN1-NODE8-GPU32-Post-Merge-2" |
|
PR_Github #63564 [ run ] triggered by Bot. Commit: |
|
PR_Github #63564 [ run ] completed with state |
WalkthroughThe changes forward ChangesDisaggregated precheck transfer
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant SubmitScript
participant PrecheckConfig
participant PRECHECK
participant TxSession
participant KVPages
SubmitScript->>PrecheckConfig: pass LLM_MODELS_ROOT
PrecheckConfig->>PRECHECK: export model root and configure manager
PRECHECK->>TxSession: submit and poll transfer wave
TxSession-->>PRECHECK: completed, failed, cancelled, or pending status
PRECHECK->>KVPages: release pages only after successful terminal status
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (5)
tests/scripts/perf-sanity/cache_transceiver_precheck/precheck_config.py (1)
132-139: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAnnotate and document the shared launch-script interface.
precheck_prefix_linesis called by both submit modules. Add precise parameter and return annotations. Add Google-styleArgsandReturnssections that documentllm_models_rootand the generated export lines.As per coding guidelines, “Annotate every function” and “Prefer docstrings for external interfaces, use Google-style docstrings, document public function arguments.”
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/scripts/perf-sanity/cache_transceiver_precheck/precheck_config.py` around lines 132 - 139, Update precheck_prefix_lines with precise type annotations for every parameter and its return value, and add a Google-style docstring documenting all arguments—especially llm_models_root—and that the function returns generated export lines. Keep the shared launch-script interface behavior unchanged.Source: Coding guidelines
tests/unittest/others/test_cache_transceiver_precheck_run.py (1)
380-397: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueClarify the two event lists.
_ctx_finish_runnerbinds its own list tofree_events, and the test then overrides_free_allto append to the localevents. The assertionfree_events == []therefore checks the discarded list. The test is correct, but the names invert the reader's expectation. Take the runner list as_or drop the override and assert on the runner list only.♻️ Proposed simplification
-def test_ctx_finish_wave_frees_only_after_block_all_returns_every_request(monkeypatch): - events = [] - - def check_status(at_least_request_num): - events.append(("block_all", at_least_request_num)) - return [101, 102], [] - - runner, free_events = _ctx_finish_runner(monkeypatch, check_status) +def test_ctx_finish_wave_frees_only_after_block_all_returns_every_request(monkeypatch): + calls = [] + + def check_status(at_least_request_num): + calls.append(("block_all", at_least_request_num)) + return [101, 102], [] + + runner, events = _ctx_finish_runner(monkeypatch, check_status) reqs = { } - runner._free_all = lambda owned: events.append(("free", sorted(owned))) runner.ctx_finish_wave(reqs) - assert events == [("block_all", None), ("free", [0, 1])] - assert free_events == [] + assert calls == [("block_all", None)] + assert events == [("free", [0, 1])]🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/unittest/others/test_cache_transceiver_precheck_run.py` around lines 380 - 397, Clarify the event-list usage in test_ctx_finish_wave_frees_only_after_block_all_returns_every_request by discarding the unused free_events value from _ctx_finish_runner and asserting the _free_all callback’s local events directly, or otherwise assert only the runner-owned list without checking the discarded list.tests/unittest/disaggregated/test_transceiver_bounded_polling.py (1)
421-428: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winThis test does not reach the in-loop sibling check.
wait_completecallshas_failed()before the KV loop, so the pre-existingTaskStatus.ERRORonfailed_taskreturnsWaitResult.FAILEDimmediately. The assertionspending_task.wait_calls == []confirm that. The test therefore duplicatestest_tx_session_blocking_wait_treats_task_failure_as_terminaland leaves the sibling recheck at lines 1368-1371 oftensorrt_llm/_torch/disaggregation/native/transfer.pyuncovered.To cover that path, make the sibling fail during the first wait slice.
💚 Proposed test change to exercise the sibling recheck
def test_tx_session_blocking_wait_detects_failed_sibling_behind_pending_task() -> None: pending_task = _FakeTask(TaskStatus.TRANSFERRING, wait_result=False) - failed_task = _FakeTask(TaskStatus.ERROR) + failed_task = _FakeTask(TaskStatus.TRANSFERRING, wait_result=False) session = _make_tx_session([pending_task, failed_task]) + wait = pending_task.wait + + def fail_sibling_during_wait(timeout: Optional[float] = None) -> bool: + result = wait(timeout) + failed_task.status = TaskStatus.ERROR + return result + + pending_task.wait = fail_sibling_during_wait assert session.wait_complete(blocking=True) == WaitResult.FAILED - assert pending_task.wait_calls == [] + assert pending_task.wait_calls == [0.25] assert failed_task.wait_calls == []🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/unittest/disaggregated/test_transceiver_bounded_polling.py` around lines 421 - 428, Update test_tx_session_blocking_wait_detects_failed_sibling_behind_pending_task so failed_task starts in a non-error state and transitions to TaskStatus.ERROR during pending_task’s first wait slice, allowing wait_complete(blocking=True) to reach and validate the in-loop sibling failure recheck. Preserve the assertions that the result is WaitResult.FAILED and both tasks’ wait-call behavior remains correct.tests/scripts/perf-sanity/disaggregated/gb300_deepseek-v4-pro-fp4_8k1k_con180_ctx3_dep4_gen1_dep32_eplb384_mtp3_ccb-NIXL.yaml (1)
70-70: 🩺 Stability & Availability | 🔵 TrivialNote the reduced receive deadline for the high-concurrency workload.
kv_transfer_timeout_msfeedsrx_timeout_sinKvCacheTransceiverV2.__init__(tensorrt_llm/_torch/disaggregation/transceiver.pyline 108). The 10x reduction to 60 s tightens the receive deadline. The PR description states that the targeted run does not establish resolution of the concurrency-1760, 8-CTX-worker case. Under that load a cold NIXL link can exceed 60 s and the request then fails instead of completing late. Track a follow-up run at the original concurrency before this config is used as the perf-sanity baseline.Also applies to: 101-101
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/scripts/perf-sanity/disaggregated/gb300_deepseek-v4-pro-fp4_8k1k_con180_ctx3_dep4_gen1_dep32_eplb384_mtp3_ccb-NIXL.yaml` at line 70, Restore kv_transfer_timeout_ms to its previous value for this high-concurrency perf-sanity configuration, rather than using the reduced 60000 ms receive deadline. Apply the same correction to the additionally referenced occurrence and retain the original timeout until the concurrency-1760, 8-CTX-worker follow-up run validates a shorter deadline.tensorrt_llm/_torch/disaggregation/native/transfer.py (1)
1374-1390: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winRemove the unreachable
WaitResult.TIMEOUThandling. Nowait_completeimplementation returnsWaitResult.TIMEOUT; remove the branch andtimed_outplumbing from_ctx_consensus_outcome.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tensorrt_llm/_torch/disaggregation/native/transfer.py` around lines 1374 - 1390, The _ctx_consensus_outcome flow still contains obsolete timeout handling. Remove the unreachable WaitResult.TIMEOUT branch and all timed_out plumbing from _ctx_consensus_outcome, while preserving the existing FAILED and COMPLETED outcomes and auxiliary-task waiting behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tensorrt_llm/_torch/disaggregation/native/transfer.py`:
- Around line 1355-1373: Update the wait-slice handling in TxSession’s
blockAll/wait_complete flow so nonpositive or None _timeout_s values still use a
small positive polling interval instead of becoming an unbounded
task.wait(timeout=None). Preserve the existing wait loop and has_failed()
recheck, ensuring cancellation of TRANSFERRING tasks can reach the terminal
failure result.
In `@tests/scripts/perf-sanity/cache_transceiver_precheck/README.md`:
- Around line 80-86: Update every documented command in the README that assigns
LLM_MODELS_ROOT so the model-root placeholder is quoted, including both the
dry-run and SLURM examples; preserve the existing command structure and
arguments.
In `@tests/unittest/scripts/test_perf_submit.py`:
- Around line 136-140: Update
test_extract_pytest_command_env_rejects_malformed_export to use a valid, closed
outer pytestCommand export containing an unclosed payload quote, then assert
ValueError matches "cannot parse pytestCommand payload". Add this test to the
applicable CI and QA test lists.
---
Nitpick comments:
In `@tensorrt_llm/_torch/disaggregation/native/transfer.py`:
- Around line 1374-1390: The _ctx_consensus_outcome flow still contains obsolete
timeout handling. Remove the unreachable WaitResult.TIMEOUT branch and all
timed_out plumbing from _ctx_consensus_outcome, while preserving the existing
FAILED and COMPLETED outcomes and auxiliary-task waiting behavior.
In `@tests/scripts/perf-sanity/cache_transceiver_precheck/precheck_config.py`:
- Around line 132-139: Update precheck_prefix_lines with precise type
annotations for every parameter and its return value, and add a Google-style
docstring documenting all arguments—especially llm_models_root—and that the
function returns generated export lines. Keep the shared launch-script interface
behavior unchanged.
In
`@tests/scripts/perf-sanity/disaggregated/gb300_deepseek-v4-pro-fp4_8k1k_con180_ctx3_dep4_gen1_dep32_eplb384_mtp3_ccb-NIXL.yaml`:
- Line 70: Restore kv_transfer_timeout_ms to its previous value for this
high-concurrency perf-sanity configuration, rather than using the reduced 60000
ms receive deadline. Apply the same correction to the additionally referenced
occurrence and retain the original timeout until the concurrency-1760,
8-CTX-worker follow-up run validates a shorter deadline.
In `@tests/unittest/disaggregated/test_transceiver_bounded_polling.py`:
- Around line 421-428: Update
test_tx_session_blocking_wait_detects_failed_sibling_behind_pending_task so
failed_task starts in a non-error state and transitions to TaskStatus.ERROR
during pending_task’s first wait slice, allowing wait_complete(blocking=True) to
reach and validate the in-loop sibling failure recheck. Preserve the assertions
that the result is WaitResult.FAILED and both tasks’ wait-call behavior remains
correct.
In `@tests/unittest/others/test_cache_transceiver_precheck_run.py`:
- Around line 380-397: Clarify the event-list usage in
test_ctx_finish_wave_frees_only_after_block_all_returns_every_request by
discarding the unused free_events value from _ctx_finish_runner and asserting
the _free_all callback’s local events directly, or otherwise assert only the
runner-owned list without checking the discarded list.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 0c62c6c3-d848-439d-947f-9a0a1e3e5e7d
📒 Files selected for processing (13)
jenkins/scripts/perf/local/submit.pyjenkins/scripts/perf/submit.pytensorrt_llm/_torch/disaggregation/native/transfer.pytensorrt_llm/_torch/disaggregation/transceiver.pytests/scripts/perf-sanity/cache_transceiver_precheck/README.mdtests/scripts/perf-sanity/cache_transceiver_precheck/precheck_config.pytests/scripts/perf-sanity/cache_transceiver_precheck/run_precheck.pytests/scripts/perf-sanity/disaggregated/gb300_deepseek-v4-pro-fp4_8k1k_con180_ctx3_dep4_gen1_dep32_eplb384_mtp3_ccb-NIXL.yamltests/unittest/disaggregated/test_cache_transceiver_precheck_e2e.pytests/unittest/disaggregated/test_transceiver_bounded_polling.pytests/unittest/others/test_cache_transceiver_precheck_config.pytests/unittest/others/test_cache_transceiver_precheck_run.pytests/unittest/scripts/test_perf_submit.py
b7bd98a to
f2d7cb6
Compare
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
…precheck Signed-off-by: Chien-Chun Hung <2679986+chienchunhung@users.noreply.github.com>
Signed-off-by: Chien-Chun Hung <2679986+chienchunhung@users.noreply.github.com>
f2d7cb6 to
1714136
Compare
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
|
/bot run --disable-fail-fast |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
tests/unittest/others/test_cache_transceiver_precheck_run.py (2)
83-111: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd a large exact-boundary case to the parametrization.
Only the
1024case allocates the extra reserve page.1024is a multiple oftokens_per_block, sonum_allocatedis 9 whilenum_prompt_blocksis 8.
7408is not a multiple of 128.num_allocatedandnum_prompt_blocksare both 58, so that case would still pass if the trim in_request_block_viewswere removed. Add a large exact-boundary length, such as7424(58 blocks, 59 allocated), to protect the boundary the stacked fix targets.♻️ Proposed parametrization change
-@pytest.mark.parametrize(("prompt_len", "expected_blocks"), ((1024, 8), (7408, 58))) +@pytest.mark.parametrize(("prompt_len", "expected_blocks"), ((1024, 8), (7408, 58), (7424, 58)))🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/unittest/others/test_cache_transceiver_precheck_run.py` around lines 83 - 111, Extend the parametrization of test_request_block_views_excludes_untransferred_speculative_page with a large exact-boundary prompt length such as 7424 and expect 58 verified blocks. Keep the existing 1024 and 7408 cases unchanged so the test covers both reserve-page allocation and the large exact-boundary trim in _request_block_views.
454-464: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd coverage for the
DISAGG_TRANS_ERRORstate branch.Request 1 is in the
failedlist here, soctx_finish_waveraises at thefailed_pairscheck. The later branch that inspectsreq.state == self.llm_request_state.DISAGG_TRANS_ERRORis never reached by any test in this file.Add a case where block-all reports the rid as completed but the request state is the error state. That path also must retain pages.
💚 Proposed added test
def test_ctx_finish_wave_retains_pages_on_disagg_trans_error_state(monkeypatch): runner, events = _ctx_finish_runner(monkeypatch, lambda _n: ([101], [])) reqs = {0: types.SimpleNamespace(py_request_id=101, state="error")} with pytest.raises(rp._TransferError, match=r"ctx DISAGG_TRANS_ERROR on pairs \[0\]"): runner.ctx_finish_wave(reqs) assert events == []🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/unittest/others/test_cache_transceiver_precheck_run.py` around lines 454 - 464, Add a test alongside test_ctx_finish_wave_retains_pages_when_request_failed that makes block-all report the request as completed while its state is DISAGG_TRANS_ERROR, using _ctx_finish_runner with no failed IDs and a request for pair 0. Assert ctx_finish_wave raises the DISAGG_TRANS_ERROR-specific _TransferError and that events remains empty, confirming pages are retained.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@tests/unittest/others/test_cache_transceiver_precheck_run.py`:
- Around line 83-111: Extend the parametrization of
test_request_block_views_excludes_untransferred_speculative_page with a large
exact-boundary prompt length such as 7424 and expect 58 verified blocks. Keep
the existing 1024 and 7408 cases unchanged so the test covers both reserve-page
allocation and the large exact-boundary trim in _request_block_views.
- Around line 454-464: Add a test alongside
test_ctx_finish_wave_retains_pages_when_request_failed that makes block-all
report the request as completed while its state is DISAGG_TRANS_ERROR, using
_ctx_finish_runner with no failed IDs and a request for pair 0. Assert
ctx_finish_wave raises the DISAGG_TRANS_ERROR-specific _TransferError and that
events remains empty, confirming pages are retained.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 9fc46729-afee-487d-9cda-fe1261acdbf7
📒 Files selected for processing (13)
jenkins/scripts/perf/local/submit.pyjenkins/scripts/perf/submit.pytensorrt_llm/_torch/disaggregation/native/transfer.pytensorrt_llm/_torch/disaggregation/transceiver.pytests/scripts/perf-sanity/cache_transceiver_precheck/README.mdtests/scripts/perf-sanity/cache_transceiver_precheck/precheck_config.pytests/scripts/perf-sanity/cache_transceiver_precheck/run_precheck.pytests/scripts/perf-sanity/disaggregated/gb300_deepseek-v4-pro-fp4_8k1k_con180_ctx3_dep4_gen1_dep32_eplb384_mtp3_ccb-NIXL.yamltests/unittest/disaggregated/test_cache_transceiver_precheck_e2e.pytests/unittest/disaggregated/test_transceiver_bounded_polling.pytests/unittest/others/test_cache_transceiver_precheck_config.pytests/unittest/others/test_cache_transceiver_precheck_run.pytests/unittest/scripts/test_perf_submit.py
🚧 Files skipped from review as they are similar to previous changes (11)
- jenkins/scripts/perf/local/submit.py
- tests/scripts/perf-sanity/cache_transceiver_precheck/precheck_config.py
- tensorrt_llm/_torch/disaggregation/native/transfer.py
- jenkins/scripts/perf/submit.py
- tests/unittest/disaggregated/test_cache_transceiver_precheck_e2e.py
- tests/scripts/perf-sanity/cache_transceiver_precheck/README.md
- tests/unittest/scripts/test_perf_submit.py
- tensorrt_llm/_torch/disaggregation/transceiver.py
- tests/scripts/perf-sanity/disaggregated/gb300_deepseek-v4-pro-fp4_8k1k_con180_ctx3_dep4_gen1_dep32_eplb384_mtp3_ccb-NIXL.yaml
- tests/scripts/perf-sanity/cache_transceiver_precheck/run_precheck.py
- tests/unittest/disaggregated/test_transceiver_bounded_polling.py
|
PR_Github #63870 [ run ] triggered by Bot. Commit: |
|
PR_Github #63870 [ run ] completed with state
|
|
The That matters because the two are in very different review states. #17223 is
Separately,
Worth sorting out between you before either merges. Also: |
brnguyen2
left a comment
There was a problem hiding this comment.
Approving — the comments below are optional touch-ups, not blockers.
Reviewed the prerequisite commit as the real content; the YAML edit itself is fine.
One framing note for the PR description: kv_transfer_timeout_ms and the sender wait slice are different knobs. The YAML value feeds rx_timeout_s and the py_executor request-cancel deadline (py_executor.py:6159); the sender's slice is kv_transfer_sender_future_timeout_ms (default 1000ms). So the revert restores the 60s request cancellation deadline, and it's safe now because wait_complete observes cancellation between slices rather than mistaking a slice expiry for completion. Worth saying that way in the commit message — "600s → 60s" alone reads like the thing that was failing is being re-enabled unchanged.
The main leftover is that TxSession.wait_complete can no longer return TIMEOUT, which leaves dead plumbing in check_context_transfer_status and removes the last diagnostic for a wedged sender (details inline). Otherwise the ownership contract is clearly stated and the unit tests cover the cases that matter — cancel-between-slices, failed sibling behind a pending task, and retain-on-failure for both ctx and gen.
| for task in self.kv_tasks: | ||
| if not task.wait(timeout=self._timeout_s): | ||
| return WaitResult.TIMEOUT | ||
| while not task.wait(timeout=wait_slice_s): |
There was a problem hiding this comment.
(to be fixed in PR #17223, not here) This loop has no diagnostic at all. Previously a stuck task produced a TIMEOUT and a warning; now it spins on 1s slices silently. The only escape is the executor's request-cancel deadline (kv_transfer_timeout_ms, default 60000) — if a deployment sets that to null, check_context_transfer_status(None) blocks the executor thread forever with nothing in the log.
Suggest logging inside the loop on an escalating cadence, e.g. warn once past N slices with the elapsed time and rid, so a wedged NIXL write is diagnosable from a CI log without a stack dump.
| @@ -703,8 +703,9 @@ def check_context_transfer_status( | |||
| elif result is None: | |||
| continue | |||
| elif result == WaitResult.TIMEOUT: | |||
There was a problem hiding this comment.
(to be fixed in PR #17223, not here) This branch is now unreachable for TxSession: the blocking path loops until terminal and the non-blocking path returns None, so wait_complete never yields TIMEOUT. That makes timed_out, its _ctx_consensus_outcome argument, and this (now debug-level) message dead code.
Either delete the branch and the timed_out plumbing, or keep it and make wait_complete actually return TIMEOUT after some bounded number of slices. Leaving a permanently-false branch that also happens to be the only place a stalled sender was ever logged is the worst of both.
| if not self.aux_task.wait(timeout=self._timeout_s): | ||
| return WaitResult.TIMEOUT | ||
| if self._need_aux: | ||
| if self.aux_task is None: |
There was a problem hiding this comment.
(to be fixed in PR #17223, not here) A blocking=True call returning None is surprising for the caller: check_context_transfer_status hits elif result is None: continue, so the rid stays in _send_sessions and block-all returns claiming it drained everything. Is aux_task guaranteed to be set before the first wait_complete when _need_aux is true? If it's a transient window this is fine but should say so; if it can persist, this is a silent stuck-request path (the precheck catches it as missing, production won't).
| # block boundary those tokens allocate an additional page, but the | ||
| # transceiver intentionally trims its slice to prompt_len blocks. | ||
| # Verify the same payload range instead of the untransferred page. | ||
| valid = [b for b in blocks if b >= 0][:num_prompt_blocks] |
There was a problem hiding this comment.
(to be fixed in PR #17223, not here) The [:num_prompt_blocks] slice silently absorbs the under-allocated case too: if the KV manager hands back fewer valid blocks than the prompt needs — a real bug this precheck exists to catch — verification just checks fewer blocks and passes.
Add an explicit check, e.g. if len(valid) < num_prompt_blocks: raise/return a mismatch detail naming the layer and the counts. Only the extra trailing speculative page should be trimmed.
| key, value = token.split("=", 1) | ||
| if key == name: | ||
| return value | ||
| raise ValueError(f"pytestCommand does not set leading environment variable {name}") |
There was a problem hiding this comment.
(to be fixed in PR #17223, not here) This raises when LLM_MODELS_ROOT isn't a leading assignment in pytestCommand. Today getPytestBaseCommandLine (L0_Test.groovy:1358) always emits it third, so it works — but this turns a precheck-config detail into a hard abort of the whole disagg perf submission if that Groovy list is ever reordered or the var moves into envVarsToExport. Consider falling back to os.environ.get("LLM_MODELS_ROOT") before raising, or at least referencing the Groovy site in the error message so the next person knows where to look.
Summary
kv_transfer_timeout_msfrom 600000 ms to 60000 ms for both GEN and CTX in the targeted GB300 DeepSeek V4 Pro disaggregated perf-sanity configuration.Commit structure and merge order
efe60576c2fba2b5d7521d2a307d562b266166a21714136e4dbfbe2c4570067da6572d268a0589971714136e4dbfbe2c4570067da6572d268a058997b7bd98a1049ad02eb335f86cb2cb64c057bb4495; only commit identities and history changed.main, dropping the squashed prerequisite commit so that only the timeout change remains.Because the GitHub base is still
main, the Files tab currently includes the squashed #17223 changes as well as this PR's two-line YAML change. Reviewers should review the prerequisite commit first and treat1714136eas the timeout-only change.Motivation and diagnosis
NVBug 6480621 reported KV-transfer request failures after the 60-second timeout under a high-concurrency GB300 DeepSeek V4 Pro disaggregated E2E workload.
Earlier CI attempts at 60 seconds failed in the synthetic
cache_transceiver_precheckwith byte mismatches before the real benchmark started:Those failures were not 60-second request-deadline expirations. The exact target configuration also produced the same precheck byte-corruption symptom with a 600-second timeout in Main #2875,
Post-Merge-2.The common problem was the Python sender's one-second future wait slice being treated as block-all completion. The precheck could release and reuse source KV pages while a transfer was still nonterminal. #17223 fixes that ownership contract, propagates the real model/runtime into the precheck, and excludes the intentionally untransferred MTP reserve page from exact-boundary verification.
Validation
Local:
kv_transfer_timeout_ms: 60000;b7bd98a1049ad02eb335f86cb2cb64c057bb4495;Diagnostic run on the preceding stack revision:
Fresh targeted CI with test reuse disabled: PASSED
b7bd98a1049ad02eb335f86cb2cb64c057bb44951714136e4dbfbe2c4570067da6572d268a058997has the identical tree; only the commit history was rewritten.SUCCESS: one target test passed, with zero failures or skips.GB300-44_GPUs-11_Nodes-PyTorch-Disagg-PerfSanity-CTX3-NODE1-GPU4-GEN1-NODE8-GPU32-Post-Merge-2model_dir=/scratch.trt_llm_data/llm-models/DeepSeek-V4-Pro,kv_cache_manager=V2, andtransceiver_runtime=PYTHONon all roles.gen_0passed all six combinations: three context peers × request lengths 1,024 and 7,408. Mismatch, transfer-error, and initialization-error counts were zero.Post-squash CI:
1714136ewith--disable-fail-fast.Target test:
perf/test_perf_sanity.py::test_e2e[disagg_upload-gen_only-gb300_deepseek-v4-pro-fp4_8k1k_con180_ctx3_dep4_gen1_dep32_eplb384_mtp3_ccb-NIXL]Interpretation and remaining scope
The fresh run validates the corrected precheck and the concurrency-180, 3-CTX-server gen-only CI proxy at the original 60-second request deadline.
It does not prove that the original NVBug workload is resolved:
Before closing NVBug 6480621, the reporter should rerun the original or an equivalently stressful E2E workload at 60 seconds, preferably more than once.
Review and merge readiness
This PR is ready for stacked/dependent review after or alongside #17223. Both PRs are currently non-draft.
It is not yet merge-ready:
efe60576;Before merging:
main, dropefe60576, and confirm that its remaining diff is only the two timeout values;The timeout change may be merged as a scoped CI-policy/test change once those conditions are satisfied, without claiming NVBug 6480621 closed.
Dev Engineer Review
kv_transfer_timeout_msfrom600000to60000for GEN and CTX in the targeted GB300 DeepSeek V4 Pro configuration.LLM_MODELS_ROOTexport.TxSession.wait_completeto retry until completion or failure.QA Engineer Review
Test-code changes include:
extract_pytest_command_envtests for quoted values, spaces,=characters, missing assignments, and malformed exports.test_tx_session_wait_complete_defaults_to_blocking.test-db/orqa/entries were added or modified, so these tests are not listed there.